package org.xxpay.pay.channel.guanghui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.xxpay.common.bean.result.PayException;
import org.xxpay.common.exception.PayErrorException;
import org.xxpay.common.http.HttpConfigStorage;
import org.xxpay.common.http.HttpRequestTemplate;
import org.xxpay.common.util.DateUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.entity.TransOrder;
import org.xxpay.pay.channel.BaseTrans;
import org.xxpay.pay.channel.guanghui.utils.GfhBank;
import org.xxpay.pay.channel.guanghui.utils.GhSignUtils;
import org.xxpay.pay.channel.shengfutong.SftpayConfig;

import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

@Component
public class GhpayTransService extends BaseTrans {

    private final static String logPrefix = "【广汇代付】";
    private final static String AGENT_PAY_ACCOUNT_CODE= "/payment/invoke";

    @Override
    public String getChannelName() {
        return GhpayConfig.CHANNEL_NAME;
    }

    /**
     * 代付订单
     *
     * @param transOrder
     * @return
     */
    @Override
    public JSONObject trans(TransOrder transOrder) {
        JSONObject retObj = buildRetObj();
        GhpayConfig ghpayConfig = new GhpayConfig(getTransParam(transOrder));
        Map<String, Object> parameters = buildRequstParam(ghpayConfig, transOrder);
        _log.info("{}申请代付请求参数：{}", logPrefix, parameters.toString());
        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
        httpConfigStorage.setMaxTotal(5);
        httpConfigStorage.setDefaultMaxPerRoute(3);
        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(httpConfigStorage);
        JSONObject origin = requestTemplate.postForObject(getReqUrl(ghpayConfig.getRequestUrl(), AGENT_PAY_ACCOUNT_CODE), parameters, JSONObject.class);
        _log.info("{}申请代付响应参数：{}", logPrefix, origin.toJSONString());

        retObj.put("isSuccess", false);
        retObj.put("transOrderId", transOrder.getTransOrderId());
        if (StringUtils.equals(SftpayConfig.RESPONSE_RESULT_SUCCESS, origin.getString("status"))) {
            retObj.put("channelOrderNo", origin.getString("transaction_id"));
            retObj.put("isSuccess", true);
            // 1. 处理中 2. 成功 3. 失败
            retObj.put("status", 1);
            return retObj;
        }
        // 1. 处理中 2. 成功 3. 失败
        retObj.put("status", 3);
        retObj.put(PayConstant.RESULT_PARAM_ERRDES, "下单失败[" + origin.getString("msg") + "]");
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
        return retObj;
    }

    /**
     * 余额查询
     * @param payParam
     * @return
     */
    @Override
    public JSONObject balance(String payParam) {
       return null;
    }

    /**
     * 获取账户数字编码 accountcode
     * @param ghpayConfig
     * @param transOrder
     * @return
     */

    private String getAccountCode(GhpayConfig ghpayConfig, TransOrder transOrder){
        Map<String,Object> reqMap = Maps.newHashMap();
        reqMap.put("merno",ghpayConfig.getMchId());
        reqMap.put("method","payment.loadSmsCode");

        Map<String,Object> data = new TreeMap();
        data.put("requestId",transOrder.getTransOrderId());//请求唯一订单号
        data.put("orgId",ghpayConfig.getAppId());//机构号
        data.put("timestamp", DateUtils.YYYYMMDDHHMMSS.format(new Date()));
        data.put("productId",ghpayConfig.getPayProduct());//产品Id
        data.put("dataSignType","1");//上送的业务参数是否加密，为空默认为明文传输 0-不加密，明文传输 1-DES加密，密文传输
        data.put("businessData",getBusinessData(transOrder,ghpayConfig));//对应产品交互业务数据
        data.put("signData", GhSignUtils.setSign(data,ghpayConfig));
        _log.info("{}获取验证码请求报文：{}", logPrefix,JSONObject.toJSONString(data));


        HttpRequestTemplate httpRequestTemplate = new HttpRequestTemplate(null);
        JSONObject res = httpRequestTemplate.postForObject(getReqUrl(ghpayConfig.getRequestUrl(),AGENT_PAY_ACCOUNT_CODE), data, JSONObject.class);

        _log.info("{}获取验证码响应报文：{}", logPrefix,res.toJSONString(data));
        String json = res.getJSONObject("result").getString("accountinfo");
        if (StringUtils.isNotBlank(json)){
            json = json.substring(1,json.length()-1);
            JSONObject ret = JSONObject.parseObject(json);
            return ret.getString("accountcode");
        }
        throw new PayErrorException(new PayException(res.getString("respCode"), res.getString("respMsg")));
    }

    /**
     * 构建实时代付请求体参数
     *
     * @return
     */
    private Map<String, Object> buildRequstParam(GhpayConfig ghpayConfig, TransOrder transOrder) {
        Map<String,Object> data = new TreeMap();
        data.put("requestId",transOrder.getTransOrderId());//请求唯一订单号
        data.put("orgId",ghpayConfig.getAppId());//机构号
        data.put("timestamp", DateUtils.YYYYMMDDHHMMSS.format(new Date()));
        data.put("productId",ghpayConfig.getPayProduct());//产品Id
        data.put("dataSignType","1");//上送的业务参数是否加密，为空默认为明文传输 0-不加密，明文传输 1-DES加密，密文传输
        data.put("businessData",getBusinessData(transOrder,ghpayConfig));//对应产品交互业务数据
        data.put("signData", GhSignUtils.setSign(data,ghpayConfig));
        _log.info("{}请求报文：{}", logPrefix,JSONObject.toJSONString(data));
        return data;
    }

    /**
     * 构建代付请求业务参数
     * @param transOrder
     * @param ghpayConfig
     * @return
     */
    private String getBusinessData(TransOrder transOrder,GhpayConfig ghpayConfig) {
        Map<String, Object> busMap = Maps.newHashMap();
        busMap.put("merno",ghpayConfig.getMchId()); //商户号
        busMap.put("method","payment.doPayment"); //业务编号
        busMap.put("accountcode",getAccountCode(ghpayConfig,transOrder)); //账户数字编号
        busMap.put("accounttype","1"); //账户类型
        busMap.put("amount",transOrder.getAmount()); //交易金额
        busMap.put("order_id",transOrder.getTransOrderId()); //订单号
        busMap.put("bank_unionid", transOrder.getBankType()); //支行联行号
        String banckName = GfhBank.valueOf(transOrder.getBankCode()).getName();
        String banckCode = GfhBank.valueOf(transOrder.getBankCode()).getCode();
        busMap.put("cardname", banckName); //银行名称
        busMap.put("bank_code", banckCode); //银行卡编号
        busMap.put("cardno", transOrder.getAccountNo());//持卡人姓名
        busMap.put("name", transOrder.getAccountName());
        return GhSignUtils.getEncryptionDate(busMap,ghpayConfig);
    }

}
